// NFC_09 [OpenGL Gears Applet].nova /* * 3-D gear wheels. This program is in the public domain. * * Brian Paul */ /* Conversion to Nova by Robert Platt */ // Using namespace declarations. using Library.Math; using Library.NFC; using Library.OpenGL; // The applet class. class GearsApplet : Applet, IRun { // "gears" data members. private float M_PI; private float view_rotx, view_roty, view_rotz; private uint gear1, gear2, gear3; private float angle; private bool active; // The window's OpenGL rendering context. private RenderingContext renderingContext; // Application class's "main" function. public static void main( String[] args ) { // Output the keyboard contols. Stream.write( "Keyboard controls:\n" + " left = rotate y-axis +ve\n" + " right = rotate y-axis -ve\n" + " up = rotate x-axis +ve\n" + " down = rotate x-axis -ve\n" + " z = rotate z-axis +ve\n" + " shift + z = rotate z-axis -ve\n" ); // Create a new applet window with a new applet instance. AppletWindow window = new AppletWindow( new GearsApplet( ), "NFC_09 [OpenGL Gears Applet]", 640, 640 ); // Show the applet window. window.show( true ); // Process the applet window's events. window.processEvents( ); } // Initialize the applet. public virtual void onInit( ) { // Initialize the "gears" data members. M_PI = 3.14159265f; view_rotx = 20.0f; view_roty = 30.0f; view_rotz = 0.0f; angle = 0.0f; active = true; // Create an OpenGL rendering context. renderingContext = OpenGL.createContext( graphics ); // Make the new rendering context the current one. OpenGL.makeCurrent( graphics, renderingContext ); // Initialize the context. float[] pos = { 5.0f, 5.0f, 10.0f, 0.0f }; float[] red = { 0.8f, 0.1f, 0.0f, 1.0f }; float[] green = { 0.0f, 0.8f, 0.2f, 1.0f }; float[] blue = { 0.2f, 0.2f, 1.0f, 1.0f }; OpenGL.glLightfv( OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, pos ); OpenGL.glEnable( OpenGL.GL_CULL_FACE ); OpenGL.glEnable( OpenGL.GL_LIGHTING ); OpenGL.glEnable( OpenGL.GL_LIGHT0 ); OpenGL.glEnable( OpenGL.GL_DEPTH_TEST ); /* make the gears */ gear1 = OpenGL.glGenLists( 1 ); OpenGL.glNewList( gear1, OpenGL.GL_COMPILE ); OpenGL.glMaterialfv( OpenGL.GL_FRONT, OpenGL.GL_AMBIENT_AND_DIFFUSE, red ); gear( 1.0f, 4.0f, 1.0f, 20, 0.7f ); OpenGL.glEndList( ); gear2 = OpenGL.glGenLists( 1 ); OpenGL.glNewList( gear2, OpenGL.GL_COMPILE ); OpenGL.glMaterialfv( OpenGL.GL_FRONT, OpenGL.GL_AMBIENT_AND_DIFFUSE, green ); gear( 0.5f, 2.0f, 2.0f, 10, 0.7f ); OpenGL.glEndList( ); gear3 = OpenGL.glGenLists( 1 ); OpenGL.glNewList( gear3, OpenGL.GL_COMPILE ); OpenGL.glMaterialfv( OpenGL.GL_FRONT, OpenGL.GL_AMBIENT_AND_DIFFUSE, blue ); gear( 1.3f, 2.0f, 0.5f, 10, 0.7f ); OpenGL.glEndList( ); OpenGL.glEnable( OpenGL.GL_NORMALIZE ); // Create a new thread to update the applet. Thread updateThread = new Thread( this, null ); // Start the thread. updateThread.start( ); } // Resize the applet. public virtual void onSize( int width, int height ) { // Prevent a divide by zero error. if ( width == 0 ) { // Make the height equal to one if zero. width = 1; } double h = (double)height / (double)width; OpenGL.glViewport( 0, 0, width, height ); OpenGL.glMatrixMode( OpenGL.GL_PROJECTION ); OpenGL.glLoadIdentity( ); OpenGL.glFrustum( -1.0, 1.0, -h, h, 5.0, 60.0 ); OpenGL.glMatrixMode( OpenGL.GL_MODELVIEW ); OpenGL.glLoadIdentity( ); OpenGL.glTranslatef( 0.0f, 0.0f, -40.0f ); } // Paint the applet. public virtual void onPaint( ) { // Draw the gears. OpenGL.glClear( OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT ); OpenGL.glPushMatrix( ); OpenGL.glRotatef( view_rotx, 1.0f, 0.0f, 0.0f ); OpenGL.glRotatef( view_roty, 0.0f, 1.0f, 0.0f ); OpenGL.glRotatef( view_rotz, 0.0f, 0.0f, 1.0f ); OpenGL.glPushMatrix( ); OpenGL.glTranslatef( -3.0f, -2.0f, 0.0f ); OpenGL.glRotatef( angle, 0.0f, 0.0f, 1.0f ); OpenGL.glCallList( gear1 ); OpenGL.glPopMatrix( ); OpenGL.glPushMatrix( ); OpenGL.glTranslatef( 3.1f, -2.0f, 0.0f ); OpenGL.glRotatef( -2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f ); OpenGL.glCallList( gear2 ); OpenGL.glPopMatrix( ); OpenGL.glPushMatrix( ); OpenGL.glTranslatef( -3.1f, 4.2f, 0.0f ); OpenGL.glRotatef( -2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f ); OpenGL.glCallList( gear3 ); OpenGL.glPopMatrix( ); OpenGL.glPopMatrix( ); // Swap the window's OpenGL buffers. OpenGL.swapBuffers( graphics ); } // Run the applet (the update thread's method). public virtual Object run( Object arg ) { // Run while the active flag is set. while ( active ) { // Get the key state for the left arrow key. if ( getKeyState( KeyReference.VK_LEFT ) ) { // Rotate the gears. view_roty += 5.0f; } // Get the key state for the right arrow key. if ( getKeyState( KeyReference.VK_RIGHT ) ) { // Rotate the gears. view_roty -= 5.0f; } // Get the key state for the up arrow key. if ( getKeyState( KeyReference.VK_UP ) ) { // Rotate the gears. view_rotx += 5.0f; } // Get the key state for the down arrow key. if ( getKeyState( KeyReference.VK_DOWN ) ) { // Rotate the gears. view_rotx -= 5.0f; } // Get the key state for the down arrow key. if ( getKeyState( KeyReference.VK_Z ) ) { if ( getKeyState( KeyReference.VK_SHIFT ) ) { // Rotate the gears. view_rotz -= 5.0f; } else { // Rotate the gears. view_rotz += 5.0f; } } // Repaint the applet. repaint( ); // Increment the angle of the gears. angle += 1.0f; } // Set the current OpenGL context to null. OpenGL.makeCurrent( null, null ); // Delete the OpenGL context. OpenGL.deleteContext( renderingContext ); return null; } // On close event handler. public virtual void onClose( ) { // Set the active flag to false to stop the rendering thread. active = false; } /** Draw a gear wheel. You'll probably want to call this function when building a display list since we do a lot of trig here. Input: inner_radius - radius of hole at center outer_radius - radius at center of teeth width - width of gear teeth - number of teeth tooth_depth - depth of tooth **/ private void gear( float inner_radius, float outer_radius, float width, int teeth, float tooth_depth ) { int i; float r0, r1, r2; float angle, da; float u, v, len; r0 = inner_radius; r1 = outer_radius - tooth_depth / 2.0f; r2 = outer_radius + tooth_depth / 2.0f; da = 2.0f * M_PI / teeth / 4.0f; OpenGL.glShadeModel( OpenGL.GL_FLAT ); OpenGL.glNormal3f( 0.0f, 0.0f, 1.0f ); // Draw the front face. OpenGL.glBegin( OpenGL.GL_QUAD_STRIP ); for ( i = 0; i <= teeth; i++ ) { angle = (float)i * 2.0f * M_PI / teeth; OpenGL.glVertex3f( r0 * Math.cos( angle ), r0 * Math.sin( angle ), width * 0.5f ); OpenGL.glVertex3f( r1 * Math.cos( angle ), r1 * Math.sin( angle ), width * 0.5f ); OpenGL.glVertex3f( r0 * Math.cos( angle ), r0 * Math.sin( angle ), width * 0.5f ); OpenGL.glVertex3f( r1 * Math.cos( angle + 3.0f * da ), r1 * Math.sin( angle + 3.0f * da ), width * 0.5f ); } OpenGL.glEnd( ); // Draw the front sides of the teeth. OpenGL.glBegin( OpenGL.GL_QUADS ); da = 2.0f * M_PI / teeth / 4.0f; for ( i = 0; i < teeth; i++ ) { angle = (float)i * 2.0f * M_PI / teeth; OpenGL.glVertex3f( r1 * Math.cos( angle ), r1 * Math.sin( angle ), width * 0.5f ); OpenGL.glVertex3f( r2 * Math.cos( angle + da ), r2 * Math.sin( angle + da ), width * 0.5f ); OpenGL.glVertex3f( r2 * Math.cos( angle + 2.0f * da ), r2 * Math.sin( angle + 2.0f * da ), width * 0.5f ); OpenGL.glVertex3f( r1 * Math.cos( angle + 3.0f * da ), r1 * Math.sin( angle + 3.0f * da ), width * 0.5f ); } OpenGL.glEnd( ); OpenGL.glNormal3f( 0.0f, 0.0f, -1.0f ); // Draw the back face. OpenGL.glBegin( OpenGL.GL_QUAD_STRIP ); for ( i = 0; i <= teeth; i++ ) { angle = (float)i * 2.0f * M_PI / teeth; OpenGL.glVertex3f( r1 * Math.cos( angle ), r1 * Math.sin( angle ), -width * 0.5f ); OpenGL.glVertex3f( r0 * Math.cos( angle ), r0 * Math.sin( angle ), -width * 0.5f ); OpenGL.glVertex3f( r1 * Math.cos( angle + 3.0f * da ), r1 * Math.sin( angle + 3.0f * da ), -width * 0.5f ); OpenGL.glVertex3f( r0 * Math.cos( angle ), r0 * Math.sin( angle ), -width * 0.5f ); } OpenGL.glEnd( ); // Draw the back sides of the teeth. OpenGL.glBegin( OpenGL.GL_QUADS ); da = 2.0f * M_PI / teeth / 4.0f; for ( i = 0; i < teeth; i++ ) { angle = (float)i * 2.0f * M_PI / teeth; OpenGL.glVertex3f( r1 * Math.cos( angle + 3.0f * da ), r1 * Math.sin( angle + 3.0f * da ), -width * 0.5f ); OpenGL.glVertex3f( r2 * Math.cos( angle + 2.0f * da ), r2 * Math.sin( angle + 2.0f * da ), -width * 0.5f ); OpenGL.glVertex3f( r2 * Math.cos( angle + da ), r2 * Math.sin( angle + da ), -width * 0.5f ); OpenGL.glVertex3f( r1 * Math.cos( angle ), r1 * Math.sin( angle ), -width * 0.5f ); } OpenGL.glEnd( ); // Draw the outward faces of the teeth. OpenGL.glBegin( OpenGL.GL_QUAD_STRIP ); for ( i = 0; i < teeth; i++ ) { angle = (float)i * 2.0f * M_PI / teeth; OpenGL.glVertex3f( r1 * Math.cos( angle ), r1 * Math.sin( angle ), width * 0.5f ); OpenGL.glVertex3f( r1 * Math.cos( angle ), r1 * Math.sin( angle ), -width * 0.5f ); u = r2 * Math.cos( angle + da ) - r1 * Math.cos( angle ); v = r2 * Math.sin( angle + da ) - r1 * Math.sin( angle ); len = Math.sqrt( u * u + v * v ); u /= len; v /= len; OpenGL.glNormal3f( v, -u, 0.0f ); OpenGL.glVertex3f( r2 * Math.cos( angle + da ), r2 * Math.sin( angle + da ), width * 0.5f ); OpenGL.glVertex3f( r2 * Math.cos( angle + da ), r2 * Math.sin( angle + da ), -width * 0.5f ); OpenGL.glNormal3f( Math.cos( angle ), Math.sin( angle ), 0.0f ); OpenGL.glVertex3f( r2 * Math.cos( angle + 2.0f * da ), r2 * Math.sin( angle + 2.0f * da ), width * 0.5f ); OpenGL.glVertex3f( r2 * Math.cos( angle + 2.0f * da ), r2 * Math.sin( angle + 2.0f * da ), -width * 0.5f ); u = r1 * Math.cos( angle + 3.0f * da ) - r2 * Math.cos( angle + 2.0f * da ); v = r1 * Math.sin( angle + 3.0f * da ) - r2 * Math.sin( angle + 2.0f * da ); OpenGL.glNormal3f( v, -u, 0.0f ); OpenGL.glVertex3f( r1 * Math.cos( angle + 3.0f * da ), r1 * Math.sin( angle + 3.0f * da ), width * 0.5f ); OpenGL.glVertex3f( r1 * Math.cos( angle + 3.0f * da ), r1 * Math.sin( angle + 3.0f * da ), -width * 0.5f ); OpenGL.glNormal3f( Math.cos( angle ), Math.sin( angle ), 0.0f ); } OpenGL.glVertex3f( r1 * Math.cos( 0.0f ), r1 * Math.sin( 0.0f ), width * 0.5f ); OpenGL.glVertex3f( r1 * Math.cos( 0.0f ), r1 * Math.sin( 0.0f ), -width * 0.5f ); OpenGL.glEnd( ); OpenGL.glShadeModel( OpenGL.GL_SMOOTH ); // Draw the inside radius cylinder. OpenGL.glBegin( OpenGL.GL_QUAD_STRIP ); for ( i = 0; i <= teeth; i++ ) { angle = (float)i * 2.0f * M_PI / teeth; OpenGL.glNormal3f( -Math.cos( angle ), -Math.sin( angle ), 0.0f ); OpenGL.glVertex3f( r0 * Math.cos( angle ), r0 * Math.sin( angle ), -width * 0.5f ); OpenGL.glVertex3f( r0 * Math.cos( angle ), r0 * Math.sin( angle ), width * 0.5f ); } OpenGL.glEnd( ); } }